package com.obas.component.tree {

   import com.ease.framework.CommandCompletionEvent;
   import com.obas.component.tree.treeclass.ErrorNode;
   import com.obas.component.tree.treeclass.LoadingNode;
   import com.obas.component.tree.treeclass.LoadingTreeNodeFactory;
   import com.obas.component.tree.treeclass.Node;
   import com.obas.constants.TestingLibConstants;
   import com.obas.constants.StringConstants;
   import com.obas.event.RequestExplorerEvent;
   import com.obas.flex.common.util.ResourceUtil;
   import com.obas.view.menu.ProjectMenu;
   import com.obas.model.business.Explorer;
   import com.ease.common.vo.Pagination;
   import com.ease.component.controls.AutoSizeTree;
   import com.ease.component.controls.Menu;
   import com.ease.component.controls.menu.AdvancedMenu;
   import com.ease.component.controls.menu.MenuItem;
   import com.ease.component.events.AdvancedMouseEvent;

   import flash.display.DisplayObject;
   import flash.events.Event;
   import flash.events.MouseEvent;

   import mx.binding.utils.BindingUtils;
   import mx.collections.ArrayCollection;
   import mx.containers.Canvas;
   import mx.controls.listClasses.IListItemRenderer;
   import mx.controls.listClasses.ListBaseContentHolder;
   import mx.core.Container;
   import mx.events.FlexEvent;
   import mx.events.ListEvent;
   import mx.events.MenuEvent;
   import mx.events.TreeEvent;

   [Event(name="{com.obas.event.RequestExplorerEvent.REQUEST_ID}", type="com.obas.event.RequestExplorerEvent")]

   public class LoadingTree extends AutoSizeTree {

      public static const MENUITEM_TYPE_REFRESH:String = "refresh";

      public var nodeFactory:LoadingTreeNodeFactory = new LoadingTreeNodeFactory();
      [Bindable]public var menuType:int = 1;
      public var rootNode:Node;
      protected var _menuMap:Object = new Object();

      private var _treeMenu:AdvancedMenu;
      private var _menuCav:Canvas;

      public function set menu(value:AdvancedMenu):void {
         this._treeMenu = value;
      }

      public function get menu():AdvancedMenu {
         return this._treeMenu;
      }

      /**
      * Constructor
      */
      public function LoadingTree() {
         super();
         doubleClickEnabled = true;

         _treeMenu = new AdvancedMenu();
         _treeMenu.dataProvider = new Array();
         _menuMap = new Object();

         addEventListener(ListEvent.ITEM_DOUBLE_CLICK, onItemDoubleClick);
         addEventListener(ListEvent.ITEM_CLICK, onSelectedItemChanged);
         addEventListener(MouseEvent.MOUSE_DOWN, onSelectedItemChanged);
         addEventListener(FlexEvent.VALUE_COMMIT, onSelectedItemChanged);
         addEventListener(ListEvent.CHANGE, onSelectedItemChanged);

         addEventListener(TreeEvent.ITEM_OPEN, onItemOpen);
         addEventListener(AdvancedMouseEvent.RIGHT_MOUSE_DOWN, onMenuSelectedHandler);
      }

      override protected function createChildren():void {
         super.createChildren();

         if (!_menuCav) {
            _menuCav = new Canvas();
            _menuCav.visible = false;
            _menuCav.includeInLayout = false;
            buildMenu(_menuCav);
            this.addChild(_menuCav);
         }
      }

      protected function buildMenu(container:Container):void {
      }

      protected function onMenuSelectedHandler(event:MouseEvent):void {
         var rightClickItem:Node = getItemUnderMouse(event.stageX, event.stageY,
                                              dataProvider as ArrayCollection);
         if (rightClickItem == null && selectedItem != rightClickItem) {
            selectedItems = [];
         }
         else if (selectedItem != rightClickItem) {
            selectedItem = rightClickItem;
         }
      }

      public function getItemUnderMouse(x:Number, y:Number, items:ArrayCollection):Node {
         for each(var item:* in items) {
            if (!(item is Node)) {
               continue;
            }

            var itemRenderer:IListItemRenderer = itemToItemRenderer(item) as IListItemRenderer;

            if (itemRenderer != null && (itemRenderer as DisplayObject).hitTestPoint(x, y)) {
               return item;
            } else if (item.children != null) {
               var node:Node = getItemUnderMouse(x, y, item.children);
               if (node != null) {
                  return node;
               }
            }
         }

         return null;
      }

      public function getListContent():ListBaseContentHolder {
         return listContent;
      }

      protected function onItemOpen(event:TreeEvent):void {
         var node:Node = event.item as Node;
         if (node is LoadingNode) {
            return;
         }

         if (!node.initialized) {
            fetchChildrenData(node);
         }
      }

      protected function onMenuItemClick(event:MenuEvent):void {
         var node:Node = selectedItem as Node;
         var item:MenuItem = event.item as MenuItem;

         if (item.clickEventType == MENUITEM_TYPE_REFRESH) {
            fetchChildrenData(node);
         }
      }

      protected function onItemDoubleClick(event:ListEvent):void {
//         var node:Node = selectedItem as Node;
//
//         if (!node.initialized) {
//            fetchChildrenData(node);
//         } else {
//            expandItem(node, !isItemOpen(node));
//         }
      }

      protected function onSelectedItemChanged(event:Event):void {
         var selectedNode:Node = selectedItem as Node;

         if (!selectedNode || selectedNode is LoadingNode || selectedNode is ErrorNode) {
            flexContextMenu = null;
         }
         else {
            var entityMenu:Menu = getEntityMenuByNode(selectedNode);
            if (entityMenu){
               _treeMenu.removeEventListener(MenuEvent.ITEM_CLICK, onMenuItemClick);
               flexContextMenu = _treeMenu = entityMenu.menu;
               _treeMenu.addEventListener(MenuEvent.ITEM_CLICK, onMenuItemClick);
            }
         }
      }

      public function fetchChildrenData(node:Node, showLoading:Boolean = true):void {
         if (showLoading) {
            addLoadingStat(node);
         }

         callRemoteService(node);
      }

      private function addLoadingStat(node:Node):void {
         if (!node.children) {
            node.children = new ArrayCollection();
         }
         node.children.removeAll();
         node.children.addItem(new LoadingNode());
         if (!isItemOpen(node)) {
            expandItem(node, true);
         }
      }

      protected function callRemoteService(node:Node):void {
         if (node.entity is Explorer) {
            var childExp:Explorer = node.entity as Explorer;
            if (!childExp.addExplorerable) {
               removeNodeStat(node);
               return;
            }
            if (childExp.alsoFolder) {
               dispatchEvent(new RequestExplorerEvent([childExp.id], node, RequestExplorerEvent.TYPE_GET_CHILDREN_EXP));
            }
         }
         else {
            var parentExp:Explorer = getParentExp(node);
            if (parentExp.childExplorers && parentExp.childExplorers.length > 0) {
               if (!node.children) {
                  node.children = new ArrayCollection();
               }
               node.children.removeAll();
               for each(var exp:Explorer in parentExp.childExplorers) {
                  var childNode:Node = nodeFactory.createNode(exp);
                  childNode.parentNode = node;
                  node.children.addItem(childNode);
               }
               node.initialized = true;
            }
            else {
               dispatchEvent(new RequestExplorerEvent([parentExp.id], node, RequestExplorerEvent.TYPE_GET_CHILDREN_EXP));
            }
         }
      }

      [ResponseHandler("{com.obas.event.RequestExplorerEvent.RETURN_ID}")]
      public function onRequestExplorerEvent(event:CommandCompletionEvent):void {
         var loadingTreeEvent:RequestExplorerEvent = event.request as RequestExplorerEvent;
         var requestNode:Node = loadingTreeEvent.reqNode;

         if (event.error) {
            const errorMsg:String = ResourceUtil.getErrorString(StringConstants.EXPLORER_ERROR, event.error);
            addErrorStat(requestNode, errorMsg);
            return ;
         }
         var items:ArrayCollection;
         if (event.result is Pagination) {
            items = Pagination(event.result).items;
         }
         else {
            items = event.result as ArrayCollection;
         }
         appendChildren(items, requestNode);
      }

      public function addErrorStat(node:Node, error:String):void {
         node.children = new ArrayCollection();
         node.children.addItem(new ErrorNode(error));
      }

      protected function removeNodeStat(node:Node):void {
         node.children.removeAll();
      }

      public function appendChildren(result:ArrayCollection, parentNode:Node):void {
         removeNodeStat(parentNode);
         var childNode:Node = null;
         if (parentNode.entity is Explorer) {
            for each (var childEntity:Object in result) {
               if(parentNode.entity.alsoFolder) {
                  childNode = nodeFactory.createNode(childEntity);
               }
               else {
                  childNode = nodeFactory.createNode(childEntity._entity);
                  childNode.children = Explorer(parentNode.entity).leaf? null : new ArrayCollection();
               }
              childNode.parentNode = parentNode;
              parentNode.children.addItem(childNode);
              if (childEntity is Explorer && !Explorer(childEntity).display) {
                 callRemoteService(childNode);
              }
            }
         }
         else {
            var parentExp:Explorer = getParentExp(parentNode);
            for each (var childExp:Explorer in result) {
               childNode = nodeFactory.createNode(childExp);
               childNode.parentNode = parentNode;
               parentNode.children.addItem(childNode);
               if (!parentExp.childExplorers) {
                  parentExp.childExplorers = new ArrayCollection();
               }
               parentExp.childExplorers.addItem(childExp);
               if (!childExp.display) {
                  callRemoteService(childNode);
               }
            }
         }

         parentNode.initialized = true;
         expandItem(parentNode, false);
         expandItem(parentNode, true);
      }

      private function getParentExp(node:Node):Explorer {
         return node.parentNode.entity as Explorer;
      }

      protected function getEntityMenuByNode(node:Node):Menu {
         var entityMenu:Menu = _menuMap.hasOwnProperty(node.type) ? _menuMap[node.type] : null;
         if (entityMenu != null) {
            entityMenu.treeMode = true;
            entityMenu.selectedItems = [node.entity];
         }
         return entityMenu;
      }

      protected function getMenuDp(node:Node):XML {
         return null
      }

   }
}
